home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / DATETIME / UNIXTM / UNIXTIME.PAS < prev    next >
Pascal/Delphi Source File  |  1996-05-16  |  13KB  |  346 lines

  1. {------------------------------------------------------------------------------}
  2. {- Unit       : UNIXTIME.PAS                                                  -}
  3. {- Programmer : Todd Fiske                                                    -}
  4. {-                                                                            -}
  5. {- Purpose    : Unix Date/Time conversion routines                            -}
  6. {-                                                                            -}
  7. {- Revision   : 02/13/1994 - first version                                    -}
  8. {- History      01/16/1995 - cleaned up for uploading, added string functions -}
  9. {-              05/16/1996 - fixed bug: secs_per_day was 3660, now 3600       -}
  10. {-              05/16/1996 - fixed bug: PackUnixTime was adding an extra day  -}
  11. {-                           to dates in a leap year but before the leap day  -}
  12. {-                                                                            -}
  13. {- Language   : Turbo Pascal 7.0                                              -}
  14. {-                                                                            -}
  15. {------------------------------------------------------------------------------}
  16.  
  17. unit unixtime;
  18.  
  19. {------------------------------------------------------------------------------}
  20.                                    interface
  21. {------------------------------------------------------------------------------}
  22.  
  23. uses
  24.    dos;
  25.  
  26. type
  27.    string_2  = string[ 2];
  28.    string_3  = string[ 3];
  29.    string_10 = string[10];
  30.  
  31. const
  32.    days_per_month : array[0..11] of byte =
  33.       ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
  34.  
  35.    months : array[0..11] of string_3 =
  36.       ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
  37.       'Nov', 'Dec' );
  38.  
  39.    days : array [0..6] of string_3 =
  40.       ( 'Thu', 'Fri', 'Sat', 'Sun', 'Mon', 'Tue', 'Wed' );
  41.  
  42.    secs_per_min   =       60;
  43.    secs_per_hour  =     3600;     { 60 * 60 }
  44.    secs_per_day   =    86400;     { 60 * 60 * 24 }
  45.    secs_per_year  = 31536000;     { 60 * 60 * 24 * 365 }
  46.    secs_per_lyear = 31622400;     { 60 * 60 * 24 * 366 }
  47.  
  48.    days_per_year  = 365;
  49.    days_per_lyear = 366;
  50.  
  51. {- Here are some more constants that illustrate another neat phenomenon I
  52. found, namely that "even" decades have 3 leap years/days, and "odd" decades
  53. have 2 leap years/days.
  54.  
  55.   "odd"    1972   1992
  56.   decades  1976   1996
  57.  
  58.   "even"   1980   2000
  59.   decades  1984   2004
  60.            1988   2008
  61. -}
  62.  
  63.    days_per_odd_dec  = 3652;
  64.    days_per_even_dec = 3653;
  65.  
  66.    secs_per_odd_dec  = 315532800; { (secs_per_year * 10) + (secs_per_day * 2); }
  67.    secs_per_even_dec = 315619200; { (secs_per_year * 10) + (secs_per_day * 3); }
  68.  
  69.    secs_to_1980      = 315532800; { secs_per_odd_dec }
  70.    secs_to_1990      = 631152000; { secs_to_1980 + secs_per_even_dec; }
  71.    secs_to_2000      = 946684800; { secs_to_1990 + secs_per_odd_dec; }
  72.  
  73.    {- Jan 01 2000 00:00:00 = 946,684,800 -}
  74.  
  75.    secs_to_19960101  = 820454400;
  76.    {- 26 years + 6 leap days,
  77.       26 * 365 = 9490,
  78.       9490 + 6 = 9496,
  79.       9496 * 86400 = 820,454,400
  80.    -}
  81.  
  82. procedure UnpackUnixTime     (t : longint; var dt : DateTime);
  83. procedure PackUnixTime       (dt : DateTime; var t : longint);
  84. function  FormatUnixTime     (t : longint) : string;
  85.  
  86. function  int2dt             (i : longint) : string_2;
  87. function  int2str            (i : longint; l : integer) : string_10;
  88. function  str2int            (s : string) : longint;
  89.  
  90. {------------------------------------------------------------------------------}
  91.                                  implementation
  92. {------------------------------------------------------------------------------}
  93.  
  94. {------------------------------------------------------------------------------}
  95. {-                                                                            -}
  96. {-           Convert Unix Date - number of seconds since Jan 1 1970           -}
  97. {-                                                                            -}
  98. {------------------------------------------------------------------------------}
  99. {------------------------------------------------------------------------------}
  100. {- Unpack Unix Time                                                           -}
  101. {-                                                                            -}
  102. {- converts Unix time longint into a DateTime record                          -}
  103. {------------------------------------------------------------------------------}
  104. procedure UnpackUnixTime(t : longint; var dt : DateTime);
  105. begin
  106.    dt.year  := 0;    { 1970 }
  107.    dt.month := 0;    { January }
  108.    dt.day   := 0;    { First }
  109.  
  110.    dt.hour  := 0;    { midnight }
  111.    dt.min   := 0;
  112.    dt.sec   := 0;
  113.  
  114.    {- writeln('Seconds since 1/1/70  ', t:12); -}
  115.           { leap year : 9999  t : 999999999999 }
  116.           { years     : 9999 }
  117.           { months    : 9999 }
  118.           { days      : 9999 }
  119.           { hours     : 9999 }
  120.           { minutes   : 9999 }
  121.           { seconds   : 9999 }
  122.  
  123.    while (t >= secs_per_year) do begin      { while more than one years worth of seconds left }
  124.       if (((dt.year + 2) mod 4) = 0) then begin   { if its a leap year }
  125.          dec(t, secs_per_day);              { subtract an extra days worth of seconds }
  126.          {- writeln('leap year         t : ', t:12); -}
  127.       end;
  128.       inc(dt.year);                         { add another year }
  129.       dec(t, secs_per_year);                { subtract a years worth of seconds }
  130.       {- writeln('years     : ', dt.year:4, '  t : ', t:12); -}
  131.    end;
  132.  
  133.    if (((dt.year + 2) mod 4) = 0) then begin      { if its a leap year }
  134.       inc(days_per_month[1]);               { add 1 more day to February }
  135.       {- writeln('leap year, February adjusted'); -}
  136.    end;
  137.  
  138.    while (t >= (days_per_month[dt.month] * secs_per_day)) do begin { while more than one month }
  139.       dec(t, days_per_month[dt.month] * secs_per_day); { subtract a months worth }
  140.       inc(dt.month);                        { add another month }
  141.       {- writeln('months    : ', dt.month:4, '  t : ', t:12); -}
  142.    end;
  143.  
  144.    while (t >= secs_per_day) do begin       { while more than one day }
  145.       dec(t, secs_per_day);                 { subtract a days worth }
  146.       inc(dt.day);                          { add another day }
  147.       {- writeln('days      : ', dt.day:4, '  t : ', t:12); -}
  148.    end;
  149.  
  150.    while (t >= secs_per_hour) do begin      { same for hours and minutes }
  151.       dec(t, secs_per_hour);
  152.       inc(dt.hour);
  153.       {- writeln('hours     : ', dt.hour:4, '  t : ', t:12); -}
  154.    end;
  155.  
  156.    while (t >= secs_per_min) do begin
  157.       dec(t, secs_per_min);
  158.       inc(dt.min);
  159.       {- writeln('minutes   : ', dt.min:4, '  t : ', t:12); -}
  160.    end;
  161.  
  162.    dt.sec := t;                             { remaining seconds }
  163.    {- writeln('seconds   : ', dt.sec:4, '  t : ', t:12); -}
  164.  
  165.    if days_per_month[1] = 29 then dec(days_per_month[1]);
  166.  
  167.    inc(dt.year, 1970);
  168.    inc(dt.month);
  169.    inc(dt.day);
  170. end;
  171.  
  172. {------------------------------------------------------------------------------}
  173. {- Pack Unix Time                                                             -}
  174. {-                                                                            -}
  175. {- converts a DateTime record into a Unix time longint                        -}
  176. {------------------------------------------------------------------------------}
  177. procedure PackUnixTime(dt : DateTime; var t : longint);
  178. var
  179.    i              : word;
  180.    days_this_year : word;
  181.    num_leap_years : word;
  182. begin
  183.    dec(dt.year, 1970);
  184.    dec(dt.month);
  185.    dec(dt.day);
  186.  
  187.    t := dt.sec;
  188.    {- writeln('seconds        : ', t:12); -}
  189.  
  190.    inc(t, dt.min  * secs_per_min);
  191.    {- writeln('minutes        : ', dt.min * secs_per_min:4); -}
  192.    {- writeln('plus minutes   : ', t:12); -}
  193.  
  194.    inc(t, longint(dt.hour) * secs_per_hour);
  195.    {- writeln('hours          : ', longint(dt.hour) * secs_per_hour:4); -}
  196.    {- writeln('plus hours     : ', t:12); -}
  197.  
  198.    {- adjust February days if leap year -}
  199.    if (((dt.year + 2) mod 4) = 0) then begin      { if its a leap year }
  200.       inc(days_per_month[1]);                     { add 1 more day to February }
  201.       {- writeln('leap year, February adjusted'); -}
  202.    end;
  203.  
  204.    {- get total number of days this year -}
  205.    days_this_year := dt.day;                     { days this month }
  206.    i := 0;
  207.    while (i < dt.month) do begin                 { days in previous months }
  208.       inc(days_this_year, days_per_month[i]);
  209.       inc(i);
  210.    end;
  211.    {- writeln('days this year : ', days_this_year:4); -}
  212.    inc(t, days_this_year * secs_per_day);
  213.    {- writeln('in seconds     : ', t:12); -}
  214.  
  215.    {- reset February days if adjusted -}
  216.    if days_per_month[1] = 29 then dec(days_per_month[1]);
  217.  
  218.    inc(t, dt.year * secs_per_year);
  219.    {- writeln('years          : ', dt.year * secs_per_year:4); -}
  220.    {- writeln('plus years     : ', t:12); -}
  221.  
  222.    num_leap_years := (dt.year + 2) div 4;        { get number of leap days }
  223.    if (((dt.year+2) mod 4) = 0) then begin       { if target year is leap year }
  224.       dec(num_leap_years);                       { back out 1 day }
  225.    end;
  226.  
  227.    {- writeln('num leap years : ', num_leap_years:4); -}
  228.  
  229.    inc(t, num_leap_years * secs_per_day);
  230.    {- writeln('plus leap days : ', t:12); -}
  231. end;
  232.  
  233. (*
  234.    1970
  235.    1971
  236.    1972 l
  237.    1973
  238.    1974
  239.    1975
  240.    1976 l
  241.    1977
  242.    1978
  243.    1979
  244.    1980 l
  245.    1981
  246.    1982
  247.    1983
  248.    1984 l
  249.    1985
  250.    1986
  251.    1987
  252.    1988 l
  253.    1989
  254.    1990
  255.    1991
  256.    1992 l
  257.    1993
  258.    1994
  259.    1995
  260.    1996 l
  261.    1997
  262.    1998
  263.    1999
  264.    2000 l
  265.  
  266.             years evenly divisible by 4 are leap years
  267.  
  268.    *except* years evenly divisible by 100 are *NOT* leap years
  269.  
  270.    *except* years evenly divisible by 400 *ARE* leap years
  271.  
  272.    So the year 2000 is a leap year, and most of us won't have to worry about
  273.    rewriting the routines in 2100 when the simple-minded "div 4" leap year
  274.    routines start failing!
  275.  
  276.    BTW, the 21st century doesn't start until 2001. The year 2000 is still the
  277.    20th century.
  278.  
  279. *)
  280.  
  281. {------------------------------------------------------------------------------}
  282. {- Format Unix Time                                                           -}
  283. {-                                                                            -}
  284. {- formats a Unix time longint into a string like this:                       -}
  285. {-                                                                            -}
  286. {-    Sun Jan 17 20:09:48 1994                                                -}
  287. {------------------------------------------------------------------------------}
  288. function FormatUnixTime(t : longint) : string;
  289. var
  290.    work : string;
  291.    dt   : DateTime;
  292. begin
  293.    UnpackUnixTime(t, dt);
  294.    FormatUnixTime :=
  295.       days[(t div secs_per_day) mod 7] +' '+
  296.       months[pred(dt.month)]      +' '+
  297.       int2str(dt.day, 2)          +' '+
  298.       int2dt (dt.hour)            +':'+
  299.       int2dt (dt.min)             +':'+
  300.       int2dt (dt.sec)             +' '+
  301.       int2str(dt.year, 4);
  302. end;
  303.  
  304. {------------------------------------------------------------------------------}
  305. {- Int2Dt                                                                     -}
  306. {------------------------------------------------------------------------------}
  307. function int2dt(i : longint) : string_2;
  308. var
  309.    s : string_2;
  310. begin
  311.    str(i:2, s);
  312.    if s[1]=' ' then s[1] := '0';
  313.    int2dt := s;
  314. end;
  315.  
  316. {------------------------------------------------------------------------------}
  317. {- Int2Str                                                                    -}
  318. {------------------------------------------------------------------------------}
  319. function int2str(i : longint; l : integer) : string_10;
  320. var
  321.    s : string_10;
  322. begin
  323.    str(i:l, s);
  324.    int2str := s;
  325. end;
  326.  
  327. {------------------------------------------------------------------------------}
  328. {- Str2Int                                                                    -}
  329. {------------------------------------------------------------------------------}
  330. function str2int(s : string) : longint;
  331. var
  332.    n : longint;
  333.    e : integer;
  334. begin
  335.    val(s, n, e);
  336.    str2int := n;
  337. end;
  338.  
  339. {------------------------------------------------------------------------------}
  340. end.
  341.  
  342. {------------------------------------------------------------------------------}
  343. {- EOF : UNIXTIME.PAS                                                         -}
  344. {------------------------------------------------------------------------------}
  345.  
  346.